package com.zhyonk.util;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 图片压缩Utils
 *
 * @author worstEzreal
 * @version V1.1.0
 * @date 2018/3/12
 */
public class PicUtils {

    private static Logger logger = LoggerFactory.getLogger(PicUtils.class);

//    public static void main(String[] args) throws IOException {
//        byte[] bytes = FileUtils.readFileToByteArray(new File("D:\\1.jpg"));
//        long l = System.currentTimeMillis();
//        bytes = PicUtils.compressPicForScale(bytes, 300, "x");// 图片小于300kb
//        System.out.println(System.currentTimeMillis() - l);
//        FileUtils.writeByteArrayToFile(new File("D:\\dd1.jpg"), bytes);
//    }

    /**
     * 根据指定大小压缩图片
     *
     * @param imageBytes  源图片字节数组
     * @param desFileSize 指定图片大小，单位kb
     * @param newSize
     * @return 压缩质量后的图片字节数组
     */
    public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize, double[] newSize) {
        if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) {
            return imageBytes;
        }
        long srcSize = imageBytes.length;
        double accuracy = getAccuracy(srcSize / 1024);
        try {
//            while (imageBytes.length > desFileSize * 1024) {
                ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
                Thumbnails.of(inputStream)
//                        .scale(accuracy)
                        .size((new Double(newSize[0])).intValue(),(new Double(newSize[1])).intValue())
                        .outputQuality(accuracy)
                        .toOutputStream(outputStream);
                imageBytes = outputStream.toByteArray();
//            }
            logger.info("【图片压缩】 | 图片原大小={}kb | 压缩后大小={}kb", srcSize / 1024, imageBytes.length / 1024);
        } catch (Exception e) {
            logger.error("【图片压缩】msg=图片压缩失败!", e);
        }
        return imageBytes;
    }

    /**
     * 自动调节精度(经验数值)
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 900) {
            accuracy = 0.85;
        } else if (size < 2047) {
            accuracy = 0.6;
        } else if (size < 3275) {
            accuracy = 0.44;
        } else {
            accuracy = 0.4;
        }
        return accuracy;
    }

    /**
     * base64转换成BufferedImage:
     * @param base64string
     * @return
     */
    public static BufferedImage base64String2BufferedImage(String base64string) {
        BufferedImage image = null;
        try {
            InputStream stream = BaseToInputStream(base64string);
            image = ImageIO.read(stream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return image;
    }

    /**
     * Base64转换成InputStream:
     * @param base64string
     * @return
     */
    private static InputStream BaseToInputStream(String base64string){
        ByteArrayInputStream stream = null;
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] bytes1 = decoder.decodeBuffer(base64string);
            stream = new ByteArrayInputStream(bytes1);
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return stream;
    }

    public static double[] getNewSize(String base64) {
        BufferedImage bufferedImage = base64String2BufferedImage(base64);
        double width = bufferedImage.getWidth();
        double height = bufferedImage.getHeight();
        double rate;
        if (width >height){
            //宽比较大
            //把宽缩放到750
            rate = width / height;
            width = 750;
            height = width / rate;
        }else {
            //高比较大
            //把高缩放到750
            rate = width / height;
            height = 750;
            width = height / rate;
        }
        return new double[]{width,height};
    }

    /**
     * 压缩/放大图片到固定的大小
     * @param w int 新宽度
     * @param h int 新高度
     */
    private static byte[] compress(int w, int h, Image oriImg, float quality) throws IOException {

        BufferedImage image = new BufferedImage(w, h,BufferedImage.TYPE_INT_RGB );
        // SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的 优先级比速度高 生成的图片质量比较好 但速度慢
        //image.getGraphics().drawImage(img, 0, 0, w, h, null); // 绘制缩小后的图
        image.getGraphics().drawImage(oriImg.getScaledInstance(w, h,  Image.SCALE_SMOOTH), 0,0,null);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 可以正常实现bmp、png、gif转jpg
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
        JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(image);
        /* 压缩质量 */
        jep.setQuality(quality, true);
        encoder.encode(image, jep);// JPEG编码
        return out.toByteArray();
    }

}